package com.ll.domain.user.biz.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ll.app.api.req.WechatUserLoginDTO;
import com.ll.app.api.req.WechatUserRegisterReqDTO;
import com.ll.app.api.req.WriteOffReqDTO;
import com.ll.base.constant.LlConstants;
import com.ll.base.dto.*;
import com.ll.base.enums.ResultCodeEnum;
import com.ll.base.exception.CustomRunTimeException;
import com.ll.base.util.DateUtil;
import com.ll.base.util.ListUtil;
import com.ll.base.util.RedisUtil;
import com.ll.base.util.ScalarUtil;
import com.ll.dal.po.UserPO;
import com.ll.domain.dingtalk.base.DingTalkUserBaseService;
import com.ll.domain.dingtalk.utils.AccessTokenUtil;
import com.ll.domain.tenant.biz.TenantDomainService;
import com.ll.domain.tenant.dto.TenantDTO;
import com.ll.domain.user.base.UserBaseService;
import com.ll.domain.user.biz.UserDomainService;
import com.ll.domain.user.convert.UserConvert;
import com.ll.domain.user.convert.UserLoginConvert;
import com.ll.domain.user.dto.UserDTO;
import com.ll.domain.user.dto.UserLoginDTO;
import com.ll.domain.user.enums.RoleEnum;
import com.ll.domain.wechat.base.WechatBaseService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.unit.DataUnit;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserDomainServiceImpl implements UserDomainService {

    private final DingTalkUserBaseService dingTalkUserBaseService;
    private final UserBaseService userBaseService;
    private final TenantDomainService tenantDomainService;
    private final RedisUtil redisUtil;



    @Override
    public UserDTO dingLogin(String requestAuthCode) {
        String token = AccessTokenUtil.getToken();
        String dingTalkUserId = dingTalkUserBaseService.login(token, requestAuthCode);
        UserDTO userDTO = dingTalkUserBaseService.getByUserId(token, dingTalkUserId);
        userBaseService.register(userDTO);

        tenantDomainService.getById(userDTO.getTenantId(), true);
        UserLoginDTO userLoginDTO = UserLoginConvert.buildDingLoginDTO(userDTO);
        reSetUserLogin(userLoginDTO);
        return userDTO;
    }

    @Override
    public UserLoginDTO getWechatCode(WechatUserLoginDTO loginDTO) {
        UserLoginDTO userLoginDTO = WechatBaseService.wechatLogin(loginDTO);
        TenantDTO tenantDTO = tenantDomainService.getById(loginDTO.getTenantId(), true);
        userLoginDTO.setTenantDTO(tenantDTO);
        if(ScalarUtil.isNotEmpty( userLoginDTO.getOtherUserId()) ){
            UserDTO userDTO = userBaseService.getByWechatUIdAndAppId(loginDTO.getTenantId(), loginDTO.getApp(), userLoginDTO.getOtherUserId());
            if(userDTO != null){
                userLoginDTO.setUid(userDTO.getId());
                userLoginDTO.setUserDTO(userDTO);
                this.reSetUserLogin(userLoginDTO);
            }else{
                log.info("新的微信用户访问 需要注册成为用户: {}", JSON.toJSONString(userLoginDTO));
            }
        }
        return userLoginDTO;
    }

    @Override
    public UserLoginDTO wechatRegister(WechatUserRegisterReqDTO registerReqDTO) {
        TenantDTO tenantDTO = tenantDomainService.getById(registerReqDTO.getTenantId(), true);

        UserDTO userDTO = userBaseService.getByWechatUIdAndAppId(registerReqDTO.getTenantId(), registerReqDTO.getApp(), registerReqDTO.getOtherUserId());
        if(userDTO != null){
            throw new CustomRunTimeException(ResultCodeEnum.USER_EXIST_ERROR);
        }

        UserPO userPO = UserLoginConvert.wechatUserRegisterDTO2UserPO(registerReqDTO);
        userBaseService.save(userPO);
        userDTO = UserConvert.PO2DTO(userPO);
        UserLoginDTO userLoginDTO = UserLoginConvert.buildDingLoginDTO(userDTO);
        userLoginDTO.setTenantDTO(tenantDTO);
        userLoginDTO.setUserDTO(userDTO);
        reSetUserLogin(userLoginDTO);
        return userLoginDTO;
    }


    @Override
    public List<String> init(Long deptId){
        String token = AccessTokenUtil.getToken();
        List<UserDTO> list = dingTalkUserBaseService.getByDeptId(token, deptId);
        userBaseService.batchInit(list);
        return ListUtil.toList(list, UserDTO::getDingTalkUserId);
    }

    public void reSetUserLogin(UserLoginDTO userLoginDTO){
        if(ScalarUtil.isEmpty(userLoginDTO.getToken())){
            userLoginDTO.setToken(UUID.randomUUID().toString());
        }

        if(userLoginDTO.getInvalidTime() == null){
            userLoginDTO.setInvalidTime(DateUtil.addDateHour(LlConstants.RedisContent.USER_LOGIN_INVALID_TIME));
        }
        redisUtil.set(LlConstants.RedisContent.USER_LOGIN+userLoginDTO.getToken(), userLoginDTO,LlConstants.RedisContent.USER_LOGIN_INVALID_TIME);
    }

    @Override
    public PageResultDTO<UserDTO> integralList(PageReqDTO pageReq) {
        pageReq.initPage();
        IPage iPage = new Page(pageReq.getPageNo(), pageReq.getPageSize());
        iPage = userBaseService.page(iPage, new LambdaQueryWrapper<UserPO>()
                .orderByDesc(UserPO::getIntegral));
        PageResultDTO<UserPO> poPageResult = new PageResultDTO<UserPO>(iPage.getRecords(), iPage.getTotal(), pageReq);
        return PageResultDTO.PageBuildDTO(poPageResult, UserConvert::PO2DTO);
    }

    @Override
    public UserDTO getByName(NameDTO nameDTO) {
        List<UserDTO> list = userBaseService.getByName(nameDTO);
        return ListUtil.first(list);
    }

    @Override
    public UserDTO getByDingUid(String dingUid) {
        UserDTO userDTO = dingTalkUserBaseService.getByUserId(AccessTokenUtil.getToken(), dingUid);
        userBaseService.register(userDTO);
        return userDTO;
//        return userBaseService.getByDingUserId(dingUid);
    }


    @Override
    public UserDTO getByTenantUid(TenantAndIdDTO tenantDTO) {
        UserDTO userDTO = userBaseService.getById(tenantDTO.getTenantId(), tenantDTO.getId(), true);
        userDTO.setIntegralRanking(userBaseService.getIntegralRanking(userDTO.getTenantId(),userDTO.getId()));
        return userDTO;
    }

    @Override
    public void writeOff(WriteOffReqDTO reqDTO) {

        UserDTO teacher = userBaseService.getByDingUserId(reqDTO.getTeacherDingId());
        List<RoleEnum> collect = teacher.getRoles().stream().filter(r -> r == RoleEnum.立木合作方).collect(Collectors.toList());
        if(ScalarUtil.isEmpty(collect)){
            throw new CustomRunTimeException(ResultCodeEnum.TARGET_LIMU_ERROR);
        }

        //检验积分是否达到
        userBaseService.checkIntegral(Collections.singletonList(reqDTO.getStudentUserId()), 50);

        userBaseService.addIntegral(reqDTO.getStudentUserId(), -50);
    }
    @Override
    public void checkIntegral(List<Long> userIds ,Integer integral){
        //检验积分是否达到
        userBaseService.checkIntegral(userIds, 50);
    }
}
